package paa.crawlers.youtube;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URL;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import paa.crawlers.delicious.Main;

import com.google.gdata.client.youtube.YouTubeService;
import com.google.gdata.data.youtube.SubscriptionEntry;
import com.google.gdata.data.youtube.SubscriptionFeed;
import com.google.gdata.data.youtube.VideoEntry;
import com.google.gdata.data.youtube.VideoFeed;
import com.google.gdata.util.ServiceException;

public class UserBasedCrawler {

	public static void main(String[] args) throws Exception {
		if (args == null || args.length < 1) {
			System.err.println("usage: java " + Main.class + " <in file> <out dir>");
			System.exit(1);
		}
		
		File file = new File(args[0]);
		File dir = new File(args[1]);
		
		if (!file.exists()) {
			System.err.println("In file does not exist.");
			System.exit(1);
		}
		
		if (!dir.isDirectory() || dir.listFiles().length < 0) {
			System.err.println("Out dir is not a directory or is not empty, exiting.");
			System.exit(1);
		}
		
		YouTubeService service = new YouTubeService("[federal_university_of_minas_gerais-ufmg]-[socialads-masters-course]-[0.001]");
		//Coletando usuarios
		Set<String> users = getUsersFromFile(file);

		//para cada usuario pegar subscriptions, playlist, favorites
		saveUserData(dir, service, users);
	}

	private static Set<String> getUsersFromFile(File file) throws Exception {
		//lendo arquivo. Pegando usuarios iniciais
		BufferedReader reader = null;
		Set<String> users = new HashSet<String>();
		
		try {
			reader = new BufferedReader(new FileReader(file));
			String line;
			while( (line = reader.readLine())!= null ) {
				if (!line.equals("")) {
					users.add(line);
				}
			}
			
			reader.close();
		} finally {
			if (reader != null) reader.close();
		}
		
		return users;
	}

	private static void saveUserData(File dir, YouTubeService service, Set<String> users) throws IOException, ServiceException {
		Set<String> toCrawl = new HashSet<String>();
		Set<String> crawled = new HashSet<String>(users);
		
		for (String username : users) {
			try {
				String subscriptions = "http://gdata.youtube.com/feeds/api/users/"+username+"/subscriptions";
				SubscriptionFeed subscriptionFeed = service.getFeed(new URL(subscriptions), SubscriptionFeed.class);
				
				for(SubscriptionEntry entry : subscriptionFeed.getEntries()) {
					String[] split = entry.getTitle().getPlainText().split(" ");
					String subs = split[split.length - 1];
					toCrawl.add(subs);
				}
				
				Thread.sleep(1000);
			} catch (Exception e) {
				System.err.println("Error occurred at user " + username + " -> " + e );
				e.printStackTrace();
			}
		}
		
		//formato do arquivo:
		//#user_name
		//#published_videos [tags]
		//#favorite [tags]
		//#subscriptions
		for (int i = 0; i < 100; i++) {
			Set<String> nextCrawl = new HashSet<String>();
			
			for (String username : toCrawl) {
				System.out.println("Crawling user: " + username);
				
				if (!crawled.contains(username)) { //Ignorando usuarios repetidos
					BufferedWriter w = null;
					try {
						File outdir = new File(dir.getAbsolutePath() + File.separator + username.charAt(0));
						if (!outdir.exists()) {
							outdir.mkdirs();
						}
							
						File userfile = new File(outdir + File.separator + username);
						
						w = new BufferedWriter(new FileWriter(userfile));
						w.write("#user: " + username);
						w.newLine();
						
						String uploads = "http://gdata.youtube.com/feeds/api/users/" + username + "/uploads";
						VideoFeed videoFeed = service.getFeed(new URL(uploads), VideoFeed.class);
						w.write("#uploads: [");
						for(VideoEntry entry : videoFeed.getEntries() ) {
							List<String> keywords = entry.getMediaGroup().getKeywords().getKeywords();
							w.write(entry.getId() + " : " + keywords + ", ");
						}
						w.write("]");
						w.newLine();
						
						Thread.sleep(1000);
						
						String favorites = "http://gdata.youtube.com/feeds/api/users/"+username+"/favorites";
						VideoFeed favoritesFeed = service.getFeed(new URL(favorites), VideoFeed.class);
						w.write("#favorites: [");
						for(VideoEntry entry : favoritesFeed.getEntries() ) {
							List<String> keywords = entry.getMediaGroup().getKeywords().getKeywords();
							w.write(entry.getId() + " : " + keywords + ", ");
						}
						w.write("]");
						w.newLine();
						
						Thread.sleep(1000);
						
						String subscriptions = "http://gdata.youtube.com/feeds/api/users/"+username+"/subscriptions";
						SubscriptionFeed subscriptionFeed = service.getFeed(new URL(subscriptions), SubscriptionFeed.class);
						
						w.write("#subscriptions: [");
						for(SubscriptionEntry entry : subscriptionFeed.getEntries()) {
							String[] split = entry.getTitle().getPlainText().split(" ");
							String subs = split[split.length - 1];
							w.write(subs + ", ");
							nextCrawl.add(subs);
						}
						w.write("]");
						w.newLine();
						
						Thread.sleep(1000);
						
						crawled.add(username);
					} catch (Exception e) {
						System.err.println("Error occurred at user " + username + " -> " + e );
						e.printStackTrace();
					} finally {
						if (w != null) w.close();
					}
				}
			}
			
			toCrawl = nextCrawl;
		}
	}
	
}
